#include <std.h>
#include <system.h>
#include <pio.h>

static unsigned long *page_directory,*page_table;

char *pgerr="Page error.";
#define MAX_PG_PER_DIR 1024
#define ADDRESS_SELECT 0xfffff000
#define PAGE_TYPE 0xfff
#define PAGE_SIZE 0x1000

#define ALLOC0 0x0		//Free page
#define K_PAGE 0x200
#define ALLOC2 0x400
#define ALLOC3 0x600
#define ALLOC4 0x800
#define ALLOC5 0xa00
#define ALLOC6 0xc00
#define MM_PAGE 0xe00
#define FREE_PAGE 	0xfffff1ff
#define ALLOC_TYPE_SHIFT 9

#define PGOCC 0xe00

#define MEM_BASE	0x200000
#define MEM_KERNEL	0x100000
/*

0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
|========================================================|  |=====|  |==|  |  |  |==|  |==|  |
				Page phys address							 Avail    Rs   D  A   Rs    Ty   P
31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9  8  7  6  5  4  3  2  1  0

D	dirty
A	accessed
P	present
Ty	00	User Read
Ty	01	User Write
Ty	10	Supervisor Read
Ty	11	Supervisor Write

		Page directory base
				|
				|
			Page table
				|
				|
			Page frame

*/

#define PGP 1
#define PGA 0xfffffffe

#define ACCESSED 0x20
#define DIRTY 0x40

#define TYUR 0
#define TYUW 2
#define TYSR 4
#define TYSW 6

#define SUPER 4
#define USER  0xffffffff-SUPER
#define WRITE 2
#define READ  0xffffffff-WRITE 

#define UR 	TYUR+PGP
#define UW	TYUW+PGP
#define SR	TYSR+PGP
#define SW	TYSW+PGP

void enable_pg();
void disable_pg();
void set_page_dir(unsigned long);

#define select_pde(n) page_table=(unsigned long *)(page_directory[n]&ADDRESS_SELECT);

extern unsigned long start,end;

#define pte_set_present(n) page_table[n]|=PGP
#define pte_set_absent(n) page_table[n]&=PGA
#define pte_is_present(n) (page_table[n]&PGP)
#define pte_set_perm_user(n) page_table[n]&=USER
#define pte_set_perm_super(n) page_table[n]|=SUPER
#define pte_set_perm_read(n) page_table[n]&=READ
#define pte_set_perm_write(n) page_table[n]|=WRITE //Set permissions of a page table entry
#define pte_is_accessed(n) (page_table[n]&ACCESSED) //Accessed bit
#define pte_is_dirty(n) (page_table[n]&DIRTY) //Dirty bit
#define pte_get_map(n) (page_table[n]&ADDRESS_SELECT) //Calculate mapped address from the page table entry

#define pde_set_present(n) page_directory[n]|=PGP
#define pde_set_absent(n) page_directory[n]&=PGA
#define pde_is_present(n) (page_directory[n]&PGP)
#define pde_set_perm_user(n) page_directory[n]&=USER
#define pde_set_perm_super(n) page_directory[n]|=SUPER
#define pde_set_perm_read(n) page_directory[n]&=READ
#define pde_set_perm_write(n) page_directory[n]|=WRITE
#define pde_is_accessed(n) (page_directory[n]&ACCESSED)
#define pde_is_dirty(n) (page_directory[n]&DIRTY)
#define pde_get_map(n) (page_directory[n]&ADDRESS_SELECT)

void init_pg()
{
	int i;
	//enable_pg();
}

void restore_pg()
{
	//enable_pg();
}
